/****************************************************************************************
**  File: ShaderProgram.hpp
**  Author: Asteroth
**  Date: 18/05/2013
****************************************************************************************/

#ifndef __ZEN_SHADER_PROGRAM_HPP__
#define __ZEN_SHADER_PROGRAM_HPP__

#include "../gl.hpp"

#include "ShaderUniforms.hpp"
#include "Shader.hpp"

namespace zen {

	namespace video {

		class ShaderProgram {
		public:

			ShaderUniforms uniforms;


		private:

			GLuint handle;
			bool linked;


		public:

			ShaderProgram() {
				handle = 0;
				linked = false;
			}

			~ShaderProgram() {
				if (this->handle != 0)
					glDeleteProgram(this->handle);
			}

			bool isLinked() {return linked;}

			bool link() {
				if (this->handle != 0) {
					glLinkProgram(this->handle);
					GLint tmp;
					glGetProgramiv(this->handle, GL_LINK_STATUS, &tmp);
					this->linked = tmp == GL_TRUE;
				}
				this->uniforms.setChanged();
				return this->linked;
			}

			bool use() {
				if (this->handle != 0) {
					glUseProgram(this->handle);
					this->uniforms.relinkUniforms(this->handle);
					return true;
				}
				return false;
			}

			bool attachShader(const Shader* shader) {
				if (this->handle == 0)
					this->handle = glCreateProgram();
				if (this->handle != 0 && shader->handle != 0 && shader->compiled) {
					glAttachShader(this->handle, shader->handle);
					return true;
				}
				return false;
			}

			bool detachShader(const Shader* shader) {
				if (this->handle != 0 && shader->handle != 0) {
					glDetachShader(this->handle, shader->handle);
					return true;
				}
				return false;
			}


		};

	} // namespace video

} // namespace zen

#endif // __ZEN_SHADER_MANAGER_HPP__